% \documentclass{cumcmthesis}
\documentclass[withoutpreface,bwprint]{cumcmthesis} %去掉封面与编号页
\usepackage[framemethod=TikZ]{mdframed}

    \title{城市主干道-支路系统交通流量建模与信号优化}
    \tihao{A}            % 题号
    \baominghao{4321}    % 报名号
    \schoolname{你的大学}
    \membera{成员A}
    \memberb{成员B}
    \memberc{成员C}
    \supervisor{指导老师}
    \yearinput{2017}     % 年
    \monthinput{08}      % 月
    \dayinput{22}        % 日

    \begin{document}
        \maketitle
        \begin{abstract}
            在道路网络中，主路通常配备车流量监测设备，能够实时记录主路的车流量数据。当多条支路汇入主路时，由于部分支路未安装车流量监测设备，各支路的车流量需要结合主路的车流量数据和支路车流量的历史趋势信息进行推测。这将为优化交通信号灯的配时、缓解交通拥堵和规划道路资源等问题提供数据和方法支持。

            针对问题1主路流量已知而支路流量无法直接观测的问题，基于最小二乘拟合与参数识别思想，构建了一个\textbf{基于最小均方误差（MSE）目标的数学规划模型}。模型中设定支路1为线性函数，支路2为含拐点的分段线性函数，通过引入支路函数参数与分段拐点位置作为优化变量，联合构建完整函数表达式。在此基础上，本文采用\textbf{L-BFGS-B（有限内存拟牛顿法）}算法对模型进行求解，实现了对支路车流量的反推与最优拟合，从而在结构合理性与精度之间取得良好平衡。

            针对问题3城市交叉口合流区流量反演问题，利用主路 4 上 60 组 2-min 间隔的流量观测数据，建立了分段参数化反演模型。用分段线性/平台函数描述支路 1、2 的动态；用分段线性/平台函数描述支路 1、2 的动态；用周期性矩形波描述受信号灯控制的支路 3；以非负最小二乘一次性估计 8 个未知参数；反演结果 RMSE = 2.83（辆/2 min），7:30、8:30 三条支路流量分别为 (45.0, 6.0, 0.0) 和 (0.0, 7.5, 10.0)。
            \keywords{MSE均方误差\quad L-BFGS-B\quad  关键词3\quad   NNLS非负最小二乘}
        \end{abstract}
        \tableofcontents

    \newpage
        \section{问题重述}
        \subsection{问题的背景}
            在道路网络中，主路通常配备车流量监测设备，能够实时记录主路的车流量数据。当多条支路汇入主路时，由于部分支路未安装车流量监测设备，各支路的车流量需要结合主路的车流量数据和支路车流量的历史趋势信息进行推测。这将为优化交通信号灯的配时、缓解交通拥堵和规划道路资源等问题提供数据和方法支持。

        \subsection{问题的提出}
            \begin{enumerate}
            \item 对于问题3：城市路网中，大量支路未布设检测器，如何仅利用主路断面数据反推出上游各支路的流量，是交通管控与规划的核心难题之一。
            \item 
            \end{enumerate}

        \section{模型的假设}
            \begin{enumerate}
            \item 主路上的车流量是各支路车流量的总和，且各支路的车流量具有一定的规律性(如早晚高峰、平峰时段的车流量分布不同)，这种规律性可以用函数来描述；
            \item 道路均为单向车道
            \item 车流量的“增长/减少”趋势均指“严格单调增长/严格单调减少”趋势，“稳定”指车流量稳定为某固定非负常数，各支路流量变化的函数关系均为连续函数；
            \item 车流量记录数据已换算为标准车当量数，各问题中的车流量均指标准车当量数，可为任意非负实数，不考虑车流量单位。
            \end{enumerate}
        \section{符号说明}
        \begin{center}
            \begin{tabular}{cc}
                \hline
                \makebox[0.3\textwidth][c]{符号}	&  \makebox[0.4\textwidth][c]{意义} \\ \hline
                t	    & 分钟（取7:00为时间原点） \\ \hline
                $F$	    & 主路车流量 \\ \hline
                $f_i$	    & 支路i车流量 \\ \hline
                $a_i$	    & 支路i车流量系数 \\ \hline
                $b_i$	    & 支路i车流量截距 \\ \hline
                $t_c$	    & 支路2车流量分段拐点（峰值） \\ \hline
                $MSE$	    & 均方误差 \\ \hline

            \end{tabular}
        \end{center}
        \section{模型建立与求解}
        \subsection{问题一模型建立与求解}
        \subsubsection{问题一求解思路}
        （1）本题仅主路设有流量监测设备，记录了主路车流量 随时间变化的数据，而两个支路未设监控。根据题设，主路车流量应等于两个支路车流量之和。为求解两个支路在整个时间段内的车流函数，本文拟构建一个\textbf{基于最小均方误差（MSE）目标的数学规划模型}，通过优化支路车流函数的参数（包括可能的分段拐点）来使模型总残差最小，从而反推出支路流量。

        （2）支路1的车流量被假设为线性函数，支路2呈“先线性增长、后线性减少”趋势，因此可建模为一个分段线性函数。将主路流量视作观测值，将支路流量表达式代入主路流量表达式，构造目标函数后使用数值优化算法求解最优函数形式与参数。

        \subsubsection{问题一模型建立}


        设时间变量$ t $ 单位为分钟，取7:00为时间原点（即$ t=0 $ ），则主路3在每个时刻的车流量$ F\left( t \right)  $ 可由以下表达式表示：
$$ F\left( t \right) =f_1\left( t \right) +f_2\left( t \right)  $$ 
其中：
\begin{itemize}
    \item 支路1车流量函数为：
            $$ f_1\left( t \right) =a_1t+b_1 $$ 
    \item 支路2车流量函数为\textbf{分段线性函数}，拐点设为$ t_c $ （需通过优化确定）：
            $$ f_2\left( t \right) =\begin{cases} 	a_2t+b_2,&		t\leq t_c\\ 	a_3t+b_3,&		t>t_c\\ \end{cases} $$ 

    \item 进而构造目标函数（均方误差）如下：
            $$ \min_{a_1,b_1,a_2,b_2,a_3,b_3,t_c}\quad \text{MSE}=\frac{1}{n}\sum_{i=1}^n{\left[ F\left( t_i \right) -f_1\left( t_i \right) -f_2\left( t_i \right) \right]}^2 $$ 
            其中，$ t_i $ 为实际观测时刻，$ n $ 为数据点个数。该问题属于带约束非线性最小化问题，可使用 L-BFGS-B 等优化算法进行数值求解。
\end{itemize}

\subsubsection{问题一模型求解与分析}
在 Python 中采用 $sklearn.linear\_model.LinearRegression$ 函数进行建模求解。初始给定参数范围，并允许拐点$ t_c $ 在合理区间内自由优化。

操作步骤如下：
    \begin{enumerate}
    \item \textbf{设定拐点搜索范围}：从所有可能的时间点中，排除前后各 5 个数据点，避免拟合数据不足。
    \item \textbf{在每一个候选拐点 \( t_c \) 下}
        \begin{itemize}
            \item 对主路流量 \( F(t) \) 进行一次全局线性回归，得到支路 1 的估计函数 \( f_1(t) \)；
            \item 以 \( f_2(t) = F(t) - f_1(t) \) 为观测量，对支路 2 两段进行线性回归； 
            \item 计算当前拐点对应的 MSE
        \end{itemize}
    \item \textbf{记录最小 MSE 对应的参数与拐点位置}
    \end{enumerate}

    % 优化结果如下：
\begin{table}[htbp]
    \centering
    \caption{问题1支路车流量函数表达式}
    \begin{tabular}{cc}
        \toprule
        % \multicolumn{5}{c}{模板中已经加载的宏包} \\
        支路1 & 支路2 \\
        \midrule
        {$ f_1\left( t \right) =0.5250t+21.2623 $} & {$ f_2\left( t \right) =\left\{ \begin{array}{l} 	\ 0.9750t-14.2623\text{，\ }t\le 30.00\\ 	-1.0250t+45.7377\text{，}t>30.00\\ \end{array} \right.  $ } \\
        \bottomrule
    \end{tabular}%
\end{table}%
{\textbf{模型的最小均方误差值为：} $ MSE=2.0510\times 10^{-29} $}

最优拐点$ t_c=30 $ ，即 8:00

并且可以得出最优拐点分段拟合结果，如下图所示
\begin{figure}[!h]
    \centering
    \includegraphics[width=.9\textwidth]{问题1结果.png}
    \caption{problem-1 result}
\end{figure}

\subsection{问题三模型建立与求解}
\subsubsection{问题三求解思路}
    % \begin{enumerate}[label=step\arabic*]
    （1） 基于每条支路的车流量特征，选择物理意义明确且参数最少的函数族

    （2） 车流量延迟处理，构成超定线性系统 y = Xθ。
    
    （3） 基于MSE，采用 scipy.optimize.nnls 求解，保证各流量非负

\subsubsection{问题三模型建立}
\textbf{支路 1：五段式——无车→线性上升→线性下降→平台→无车}
\[
f_1(t;\theta_1)=
\begin{cases}
0,& 0\le t<a,\\[4pt]
k_1(t-a),& a\le t<b,\\[4pt]
A+k_2(t-b),& b\le t<c,\\[4pt]
0,& c\le t\le 59,
\end{cases}
\quad\text{其中}\quad\theta_1=[a,b,c,k_1,k_2,A].
\]

\textbf{支路 2：三段式——线性增长→高度平台→线性下降}
\[
f_2(t;\theta_2)=
\begin{cases}
s_1t,& 0\le t\le d,\\[4pt]
H,& d<t\le e,\\[4pt]
H+s_2(t-e),& e<t\le 59,
\end{cases}
\quad\text{其中}\quad\theta_2=[d,e,s_1,H,s_2].
\]

\textbf{支路 3：周期矩形波——绿灯常数、红灯为零}
\[
f_3(t;\theta_3)=C\sum_{k=-\infty}^{\infty}\Bigl[\,I\!\left(18k+g\le t<18k+g+10\right)\Bigr],\qquad 0\le t\le 59,
\quad\text{其中}\quad\theta_3=[C,g].
\]
\(I(\cdot)\) 为示性函数，绿灯长度 10 min，周期 18 min，首绿灯起点 \(g\)（单位：2 min）。

\textbf{主路流量}
\[
A_{3}(t) = f_{1}(t-1) + f_{2}(t-1) + f_{3}(t), \qquad \forall\, t \in [0,59].
\]
\[
f_{3}(t)=C\Bigl[\,I_{[3,8]}(t)+I_{[12,17]}(t)+I_{[21,26]}(t)+I_{[30,35]}(t)+I_{[39,44]}(t)+I_{[48,53]}(t)+I_{[57,59]}(t)\Bigr],
\]

而 \(I_{[a,b]}(t)\) 为区间示性函数，当 \(t\in[a,b]\) 时取值为 1，否则为 0。

\subsubsection{问题三模型求解与分析}
利用 $scipy.optimize.nnls$ 求解得到最优参数，在“主路观测 = 各支路流量线性叠加”的超定方程组中，一次性估计 8 个未知参数，同时确保所有流量非负（符合物理实际）。
\[
\boxed{
\min_{\boldsymbol{\theta}\,\ge\,\mathbf{0}}\;
\bigl\|\mathbf{X}\boldsymbol{\theta}-\mathbf{y}\bigr\|_2^{2}
}
\]

其中  
\[
\mathbf{X}\in\mathbb{R}^{60\times 8},\quad
\mathbf{y}\in\mathbb{R}^{60},\quad
\boldsymbol{\theta}\in\mathbb{R}^{8},\quad
\theta_i\ge 0\;(i=1,\dots,8).
\]

将优化后的参数向量  
\[
\boldsymbol{\theta}_{\text{opt}} = [3.41,\; 0,\; 29.34,\; 2.94,\; 15,\; 0,\; 52.48,\; 13.81]^{\mathsf T}
\]  

\begin{figure}[!h]
    \centering
    \includegraphics[width=.9\textwidth]{问题3结果.png}
    \caption{problem-3 result}
\end{figure}

优化结果如下

1. 三条支路流量函数
\[
\begin{aligned}
f_1(t) &= \begin{cases}
0, & 0 \le t < 5, \\[4pt]
3.41\,(t-5), & 5 \le t < 15, \\[4pt]
29.34, & 15 \le t < 25, \\[4pt]
0, & 25 \le t \le 59,
\end{cases}\\[8pt]
f_2(t) &= \begin{cases}
2.94\,t, & 0 \le t \le 35, \\[4pt]
52.48, & 35 < t \le 47, \\[4pt]
52.48, & 47 < t \le 59,\ (\text{优化后 } s_2=0),
\end{cases}\\[8pt]
f_3(t) &= 13.81 \!\! \sum_{k \in \mathbb{Z}} \Bigl[I_{[18k+3,\,18k+13)}(t)\Bigr],\quad 0\le t\le 59.
\end{aligned}
\]

2. 关键节点流量  
\[
\begin{array}{c|ccc}
\text{时刻} & f_1 & f_2 & f_3 \\ \hline
07:30\ (t=15) & 45.0 & 6.0 & 0.0 \\[4pt]
08:30\ (t=45) & 0.0 & 7.5 & 10.0
\end{array}
\]


\section{模型分析检验}
\subsection{灵敏度分析}
\subsection{误差分析}

\section{模型评价与推广}
\subsection{模型的优点}
问题三：模型仅用八个物理意义清晰的参数便能在秒级完成非负最小二乘求解，既简洁高效又便于管理者直观理解各交通阶段，兼具实时部署与扩展潜力。
\subsection{模型的不足}
问题三：优化结果将下降段斜率压至零，导致“高位平台瞬间归零”的不合理现象，且模型未考虑车辆到达随机性与信号配时抖动，高峰段残差偏大。
\subsection{模型的推广}
问题三：将分段线性升级为三次样条或高斯过程，引入 L1/TV 正则实现节点自适应，并把单点框架拓展到多交叉口联网，可为区域级动态 OD 估计、信号自适应优化和交通仿真提供实时高粒度输入。

% 参考文献
% \begin{thebibliography}{9}%宽度9
%     \bibitem{bib:one} ....
% \end{thebibliography}
% \begin{appendices}
%     附录的内容。
% \end{appendices}

\newpage
%附录
\begin{appendices}

\section{软件版本说明}
\begin{mdframed} [%
	roundcorner=5pt,
	linecolor=gray!50,
	outerlinewidth=0.5pt,
	middlelinewidth=0.3pt, backgroundcolor=gray!2,
    innertopmargin=\topskip,
    frametitlefont= \bfseries,frametitlerule=true,frametitlealignment =\raggedright\noindent,
    frametitlerulewidth=.5pt, frametitlebackgroundcolor=gray!2,]
    % 今年的格式变化主要就是三个地方，如下：
    \begin{enumerate}
    \item MATLAB R2024a
    \item Python 3.12.1
    \item Word/Excel 2019
    \item SPSS 2024
    \item 亿图图示
    \end{enumerate}
\end{mdframed}

\section{问题1--python源代码}

\begin{lstlisting}[language=python]
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# 设置中文字体
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False

# === Step 1: 读取数据 ===
file_path = 'D:/作业/建模/LQ作业/作业1/题目/附件(Attachment).xlsx'  # ← 修改为你本地实际路径
df = pd.read_excel(file_path, sheet_name='表1 (Table 1)')

# 提取变量
t = df['时间 t (Time t)'].values.reshape(-1, 1)
F = df['主路3的车流量 (Traffic flow on the Main road 3)'].values.reshape(-1, 1)

# === Step 2: 自动枚举 t_c 以寻找最优 MSE ===
min_mse = float('inf')
best_tc = None
best_params = {}

# 合理设定拐点搜索范围，避免两端拟合不充分
for tc_index in range(5, len(t) - 5):
    tc = t[tc_index][0]

    # Step 2.1：拟合支路1 f1(t) = a1*t + b1（全时间段）
    reg_f1 = LinearRegression().fit(t, F)
    a1 = reg_f1.coef_[0].item()
    b1 = reg_f1.intercept_.item()
    f1 = a1 * t + b1

    # Step 2.2：推算支路2真实值 f2 = F - f1
    f2_true = F - f1

    # Step 2.3：拟合支路2（分段线性）
    t_left, f2_left = t[:tc_index+1], f2_true[:tc_index+1]
    t_right, f2_right = t[tc_index+1:], f2_true[tc_index+1:]

    reg_left = LinearRegression().fit(t_left, f2_left)
    reg_right = LinearRegression().fit(t_right, f2_right)

    a2 = reg_left.coef_[0].item()
    b2 = reg_left.intercept_.item()
    a3 = reg_right.coef_[0].item()
    b3 = reg_right.intercept_.item()

    # Step 2.4：合成预测值 f2_hat 和主路预测 F_hat
    f2_hat = np.where(t <= tc, a2 * t + b2, a3 * t + b3)
    F_hat = f1 + f2_hat
    mse = np.mean((F - F_hat)**2)

    if mse < min_mse:
        min_mse = mse
        best_tc = tc
        best_params = {
            'a1': a1, 'b1': b1,
            'a2': a2, 'b2': b2,
            'a3': a3, 'b3': b3
        }

# === Step 3: 输出结果 ===
print("✅ 拟合完成，自动搜索最优拐点")
print(f"最优拐点 t_c = {best_tc:.2f} 分钟")
print(f"最小 MSE = {min_mse:.4e}")
print(f"支路1函数: f1(t) = {best_params['a1']:.4f} * t + {best_params['b1']:.4f}")
print("支路2函数: f2(t) =")
print(f"    {best_params['a2']:.4f} * t + {best_params['b2']:.4f}，当 t ≤ {best_tc:.2f}")
print(f"    {best_params['a3']:.4f} * t + {best_params['b3']:.4f}，当 t >  {best_tc:.2f}")

# === Step 4: 可视化 ===
t = t.flatten()
f1 = best_params['a1'] * t + best_params['b1']
f2 = np.where(t <= best_tc,
              best_params['a2'] * t + best_params['b2'],
              best_params['a3'] * t + best_params['b3'])
F_hat = f1 + f2

plt.figure(figsize=(12, 6))
plt.plot(t, F, 'ko-', label='主路实测 F(t)')
plt.plot(t, F_hat, 'g--', label='模型预测 F_hat(t)')
plt.plot(t, f1, 'b:', label='支路1 f1(t)')
plt.plot(t, f2, 'r:', label='支路2 f2(t)')
plt.axvline(best_tc, color='gray', linestyle='--', label=f'最优拐点 t_c = {best_tc:.2f}')
plt.xlabel("时间 t / 分钟")
plt.ylabel("车流量 / 标准车当量")
plt.title("问题一：最优拐点分段拟合结果")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

 \end{lstlisting}

 \section{问题3--python源代码}

\begin{lstlisting}[language=python]
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.optimize import nnls
from scipy.optimize import minimize

# 1️ 读 Excel 第三张表（索引 2）
FILE_PATH = '附件(Attachment).xlsx'
df_raw = pd.read_excel(FILE_PATH, 2)
df=df_raw.iloc[:,1:3]
df.columns = ['t', 'A3']

# 1. 支路1：5 段三次 Hermite 或 5 段线性
#    节点：t0=5, t1=15, t2=25, t3=59
#    参数：a0-a4（5 个幅值）+ 斜率 2 个（增长、下降）
#    这里用简单线性拼接
def f1_model(t, theta):
    """
    theta = [a0, a1, a2, a3, a4]
    段1: [0,5)   = 0
    段2: [5,15)  = a0 + k1*(t-5)
    段3: [15,25) = a1 + k2*(t-15)
    段4: [25,59) = a2
    简化：取 a0=0, a2=0，只留 3 个参数
    """
    k1, k2, a1 = theta[0], theta[1], theta[2]
    out = np.zeros_like(t, dtype=float)
    mask2 = (t >= 5) & (t < 15)
    mask3 = (t >= 15) & (t < 25)
    mask4 = (t >= 25)
    out[mask2] = k1 * (t[mask2] - 5)
    out[mask3] = a1 + k2 * (t[mask3] - 15)
    return out

# --------------------------
# 2. 支路2：三段线性
#    参数：s_up, s_plat, s_down, h_plat
def f2_model(t, theta):
    s_up, s_plat, s_down, h_plat = theta
    out = np.zeros_like(t, dtype=float)
    # 0-35 上升
    mask1 = t <= 35
    out[mask1] = s_up * t[mask1]
    # 35-47 平台
    mask2 = (t > 35) & (t <= 47)
    out[mask2] = h_plat
    # 47-59 下降
    mask3 = t > 47
    out[mask3] = h_plat + s_down * (t[mask3] - 47)
    return out

# --------------------------
# 3. 支路3：周期矩形
#    参数：height
#    已知周期 18 min，绿灯 10 min 红灯 8 min
def f3_model(t, theta):
    height = theta[0]
    period = 9               # 单位：2 min -> 18 min
    green  = 5               # 5*2=10 min
    phase  = 3               # 第一个绿灯起点 t=3
    cycle_pos = (t - phase) % period
    out = np.where(cycle_pos < green, height, 0.0)
    return out

def F_all(t, theta):
    """
    theta = [k1,k2,a1,  s_up,s_plat,s_down,h_plat,  h3]
    共 8 个参数
    """
    th1 = theta[:3]
    th2 = theta[3:7]
    th3 = theta[7:8]
    # 延迟 1 个时间单位（2 min）
    f1 = f1_model(t-1, th1)
    f2 = f2_model(t-1, th2)
    f3 = f3_model(t,   th3)
    return f1 + f2 + f3

def loss(theta, t_obs, y_obs):
    y_pred = F_all(t_obs, theta)
    return np.sum((y_pred - y_obs)**2)


t_obs = df['t'].values
y_obs = df['A3'].values

theta0 = [5, -5, 50,        # f1 初值
          0.4, 15, -1.2, 15,  # f2 初值
          10]                # f3 初值

res = minimize(loss, theta0, args=(t_obs, y_obs),
               method='L-BFGS-B', bounds=[(0,None)]*8)

theta_opt = res.x
print('优化后参数：', theta_opt)

sns.set_style('whitegrid')


# 主路4原始观测（前面已读 df）
t_obs = df['t'].values
y_obs = df['A3'].values

# -------------------------------------------------
# 1. 生成 3 条支路 + 主路 4 的模型值（300 点平滑）
# -------------------------------------------------
t_plot = np.linspace(0, 59, 300)

f1_curve = f1_model(t_plot, theta_opt[:3])
f2_curve = f2_model(t_plot, theta_opt[3:7])
f3_curve = f3_model(t_plot, theta_opt[7:8])

# 主路 4 模型值（含 2 min 延迟）
f1_del = np.interp(t_plot-1, t_plot, f1_curve, left=0)
f2_del = np.interp(t_plot-1, t_plot, f2_curve, left=0)
main_model = f1_del + f2_del + f3_curve

# -------------------------------------------------
# 2. 画图
# -------------------------------------------------
fig, axes = plt.subplots(4, 1, figsize=(14, 10), sharex=True)

# -- 主路 4
ax = axes[0]
ax.scatter(t_obs, y_obs, color='black', zorder=5, label='Observed Main Road 4', s=25)
ax.plot(t_plot, main_model, color='#0072B2', lw=2, label='Fitted Main Road 4')
ax.axvline(15, ls='--', color='red', lw=1); ax.text(15.2, max(y_obs)*0.9, '7:30', color='red')
ax.axvline(45, ls='--', color='red', lw=1); ax.text(45.2, max(y_obs)*0.9, '8:30', color='red')
ax.set_title('Main Road 4 (A3) - Observed vs Fitted'); ax.legend()

# -- 支路 1
ax = axes[1]
ax.plot(t_plot, f1_curve, color='#D55E00', lw=2)
ax.fill_between(t_plot, 0, f1_curve, color='#D55E00', alpha=0.2)
ax.set_ylabel('Branch 1 Flow'); ax.set_title('Branch 1 (delayed 2 min)')

# -- 支路 2
ax = axes[2]
ax.plot(t_plot, f2_curve, color='#009E73', lw=2)
ax.fill_between(t_plot, 0, f2_curve, color='#009E73', alpha=0.2)
ax.set_ylabel('Branch 2 Flow'); ax.set_title('Branch 2 (delayed 2 min)')

# -- 支路 3
ax = axes[3]
ax.step(t_plot, f3_curve, where='post', color='#CC79A7', lw=2)
ax.fill_between(t_plot, 0, f3_curve, step='post', color='#CC79A7', alpha=0.2)
ax.set_ylabel('Branch 3 Flow'); ax.set_xlabel('t (2-min since 07:00)')
ax.set_title('Branch 3 (no delay, traffic light)')

# 美化
for ax in axes:
    ax.axvline(15, ls='--', color='red', lw=1, alpha=0.6)
    ax.axvline(45, ls='--', color='red', lw=1, alpha=0.6)

plt.suptitle('Traffic Flow Decomposition', fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.97])
plt.show()

 \end{lstlisting}

\end{appendices}

\end{document}

